﻿using System.Windows;
using System.Windows.Media;
using System.Xml.Linq;

namespace Lib.WPF.Core;
/// <summary>
/// 扩展方法
/// </summary>
public static class VisualTreeExtensions {

    //////////////////// 查找父元素 /////////////////////////////////////////////////////////////////

    /// <summary>
    /// 查找指定类型的父元素
    /// </summary>
    public static T FindVisualParent<T>(this DependencyObject obj) where T : DependencyObject {
        while (obj != null && obj is not T) {
            obj = VisualTreeHelper.GetParent(obj);
        }
        return obj as T;
    }
    /// <summary>
    /// 查找特定名称的父元素
    /// </summary>
    public static FrameworkElement FindVisualParent(this DependencyObject obj, string ParentName) {
        while (obj != null) {
            obj = VisualTreeHelper.GetParent(obj);
            if (obj is FrameworkElement e && e.Name == ParentName) {
                return e;
            }
        }
        return null;
    }
    /// <summary>
    /// 查找满足条件的父元素
    /// </summary>
    public static DependencyObject FindVisualParent(this DependencyObject obj, Func<DependencyObject, bool> Action) {
        while (obj != null) {
            obj = VisualTreeHelper.GetParent(obj);
            if (obj != null && Action(obj)) {
                return obj;
            }
        }
        return null;
    }
    /// <summary>
    /// 查找特定条件的父元素
    /// </summary>
    public static T FindVisualParent<T>(this DependencyObject obj, Func<T, bool> Action) where T : DependencyObject {
        while (obj != null) {
            obj = VisualTreeHelper.GetParent(obj);
            if (obj is T Result && Action(Result)) {
                return Result;
            }
        }
        return null;
    }
    /// <summary>
    /// 查找指定类型的逻辑父元素
    /// </summary>
    public static T FindLogicalParent<T>(this DependencyObject obj) where T : DependencyObject {
        while (obj != null && obj is not T) {
            obj = LogicalTreeHelper.GetParent(obj);
        }
        return obj as T;
    }
   

    //////////////////// 查找子元素 /////////////////////////////////////////////////////////////////


    /// <summary>
    /// 查找指定名称的子元素
    /// </summary>
    public static T FindChildByName<T>(this DependencyObject obj, string ChildName) where T : FrameworkElement {
        if (obj == null) {
            return null;
        }
        T FoundChild = null;
        int ChildrenCount = VisualTreeHelper.GetChildrenCount(obj);
        for (int i = 0; i < ChildrenCount; i++) {
            var Child = VisualTreeHelper.GetChild(obj, i);
            if (Child is T That && That.Name == ChildName) {
                FoundChild = That;
                break;
            } else {
                FoundChild = FindChildByName<T>(Child, ChildName);
                if (FoundChild != null) {
                    break;
                }
            }
        }
        return FoundChild;
    }
    /// <summary>
    /// 查找指定类型的所有子元素
    /// </summary>
    public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject Obj) where T : DependencyObject {
        if (Obj == null) { 
            yield break; 
        }
        var Queue = new Queue<DependencyObject>();
        Queue.Enqueue(Obj);
        while (Queue.Count > 0) {
            var Current = Queue.Dequeue();
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(Current); i++) {
                var Child = VisualTreeHelper.GetChild(Current, i);
                if (Child is T Result) {
                    yield return Result;
                }
                Queue.Enqueue(Child);
            }
        }
    }

    //////////////////// 查找同辈元素 /////////////////////////////////////////////////////////////////


    /// <summary>
    /// 查找所有同辈元素
    /// </summary>
    public static IEnumerable<DependencyObject> FindSiblings(this DependencyObject obj) {
        if (obj == null) {
            yield break;
        }
        var Parent = VisualTreeHelper.GetParent(obj);
        if (Parent == null) {
            yield break;
        }
        int ChildrenCount = VisualTreeHelper.GetChildrenCount(Parent);
        for (int i = 0; i < ChildrenCount; i++) {
            var Sibling = VisualTreeHelper.GetChild(Parent, i);
            if (Sibling != obj){
                yield return Sibling;
            }
        }
    }
    /// <summary>
    /// 查找特定类型的同辈元素
    /// </summary>
    public static IEnumerable<T> FindSiblingByName<T>(this DependencyObject obj) where T : DependencyObject {
        foreach (var Sibling in FindSiblings(obj)) {
            if (Sibling is T Result) {
                yield return Result;
            }
        }
    }
    /// <summary>
    /// 查找特定类型的（第一个或特定名称）同辈元素
    /// </summary>
    public static T FindSiblings<T>(this DependencyObject obj, string Name = null) where T : FrameworkElement {
        foreach (var Sibling in FindSiblings(obj)) {
            if (Sibling is T Result) {
                if (!string.IsNullOrEmpty(Name) && Result.Name != Name) {
                    continue;
                }
                return Result;
            }
        }
        return null;
    }
    /// <summary>
    /// 使用逻辑树查找同辈元素
    /// </summary>
    public static IEnumerable<DependencyObject> FindLogicalSiblings(this DependencyObject obj) {
        if (obj == null) {
            yield break;
        }
        var Parent = LogicalTreeHelper.GetParent(obj);
        if (Parent == null) {
            yield break;
        }
        foreach (var Sibling in LogicalTreeHelper.GetChildren(Parent)) {
            if (Sibling is DependencyObject Result && Result != obj) {
                yield return Result;
            }
        }
    }

}
